﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace PlanetViewer
{
    public class TerrainDrawMask
    {
        private Terrain _Terrain;

        private VertexPositionColor[] _vertData;
        public VertexPositionColor[] Vertices { get { return _vertData; } }
        private int[] _indexData;
        public int[] Indices { get { return _indexData; } }

        private int _maskLength;
        public int _minMLength;
        public float _minMLengthF;
        public int MaskLength
        {
            get { return this._maskLength; }
            set
            {
                if (_maskLength != value)
                {
                    _maskLength = value;

                    if (_maskLength < _minMLength) _maskLength = _minMLength;
                    if (_maskLength >= this._Terrain.Length) _maskLength = this._Terrain.Length;

                    int nVerts = 3 * (_maskLength + 1);

                    _vertData = new VertexPositionColor[nVerts];
                    _indexData = util.CreateLayeredIndexArray(_maskLength, 2);

                    AdjustVertices(true);
                }
            }
        }

        private int _spine;
        private int _oldSpine;

        private Controls _Player1 { get { return this._Terrain._Planet._plViewer.Player1; } }
        private float Angle { get { if (this._Player1 != null) return this._Player1.Angle; else return 0f; } }

        /*private int _LOD = 0;
        private int _LODmax = 2;
        public int LODLength { get { return (int)((float)this.Length / (float)(this.LOD + 1)); } }
        public int LOD
        {
            get { return this._LOD; }
            set
            {
                if (value < 0) value = 0;
                if (value > this._LODmax) value = this._LODmax;

                this._LOD = value;

                this.AdjustVertices(true);
            }
        }*/

        
        public TerrainDrawMask(Terrain terrain, int maskLength)
        {
            this._Terrain = terrain;

            this._minMLength = maskLength;
            this._minMLengthF = (float)_minMLength / (float)this._Terrain.Length;

            this.MaskLength = maskLength;
        }

        public void CalculateMaskLength(float percentage)
        {
            this.MaskLength = (int)Math.Round(this._Terrain.Length * percentage);
        }

        public void AdjustVertices(bool force = false)
        {
            _spine = (int)Math.Floor(this.Angle / this._Terrain._Planet.SpineAngle);

            if (_spine != _oldSpine | force)
            {
                int S1 = _spine - (int)(this.MaskLength / 2);
                int S2 = S1 + this.MaskLength;

                VertexPositionColor B = this._Terrain.Data.BoundaryVertex;
                VertexPositionColor D = this._Terrain.Data.UndergroundVertex;
                
                for (int i = S1; i <= S2; i++)
                {
                    float ang = i * this._Terrain._Planet.SpineAngle;

                    VertexPositionColor V = util.RotateVertex(D, ang);
                    AddUndergroundVertex(V, i - S1);

                    V = util.RotateVertex(B, ang);
                    AddBoundaryVertex(V, i - S1);

                    V = util.RotateVertex(this._Terrain.Data.GetTerrainVertex(i), ang);
                    AddTerrainVertex(V, i - S1);
                }
            }

            _oldSpine = _spine;
        }

        /// <summary>
        /// Calculate new mask based on camera rotation and zoom.
        /// </summary>
        public void Update()
        {
            if (this.Angle != this._Player1._pAngle)
            {
                AdjustVertices();
            }
        }

        public void AddTerrainVertex(VertexPositionColor V, int index)
        {
            index = util.Modulo(index, (this.MaskLength + 1));
            _vertData[index + 2 * (this.MaskLength + 1)] = V;
        }

        public void AddBoundaryVertex(VertexPositionColor V, int index)
        {
            index = util.Modulo(index, (this.MaskLength + 1));
            _vertData[index + (this.MaskLength + 1)] = V;
        }
        
        public void AddUndergroundVertex(VertexPositionColor V, int index)
        {
            index = util.Modulo(index, (this.MaskLength + 1));
            _vertData[index] = V;
        }

    }
}
